#include "ClientContext.h"
#include "ITransHandler.h"
#include "NotifyProc.h"

using namespace std;
using namespace log4cplus;

Logger ClientContext::log=GetLogger(LOG4CPLUS_TEXT("ClientContext"));

ClientContext::ClientContext()
	:m_currentHandler(NULL),m_sequenceNo(0),m_threadRefCount(0),m_needRelease(false),
	m_srcSock(NULL),m_destSock(NULL),m_ovl(),m_buffer(),m_weakRefBuf(),
	m_httpRequest(),m_httpResponseHeader(new HttpResponseHeader()),m_partialTransIndex(0),
	m_translatedFileIndex(UNINITIALIZE_FILE_SIZE_INDEX),m_maxFileIndex(UNINITIALIZE_FILE_SIZE_INDEX),
	m_extContext(),m_insContext(NULL)
#if _DEBUG
	,m_debugFileHandle(NULL)
#endif
{
	InitAsyncParam(&m_ovl,&m_buffer);
}

ClientContext::~ClientContext()
{
	LOG4CPLUS_DEBUG_FMT(log,LOG4CPLUS_TEXT("Start to dispose client%d."),m_sequenceNo);
	if(m_currentHandler!=NULL)
	{
		delete m_currentHandler;
		LOG4CPLUS_DEBUG_STR(log,LOG4CPLUS_TEXT("Free translation handler finished."));
	}
	if(m_srcSock!=NULL)
	{
		::shutdown(m_srcSock,SB_BOTH);
		::closesocket(m_srcSock);
		LOG4CPLUS_DEBUG_STR(log,LOG4CPLUS_TEXT("Dispose client source socket finished."));
	}
	if(m_destSock!=NULL)
	{
		::shutdown(m_destSock,SB_BOTH);
		::closesocket(m_destSock);
		LOG4CPLUS_DEBUG_STR(log,LOG4CPLUS_TEXT("Dispose client destination socket finished."));
	}
	/*while(!HasOverlappedIoCompleted(&m_srcOvl)||!HasOverlappedIoCompleted(&m_destOvl))
	{
		::Sleep(50);
	}
	LOG4CPLUS_DEBUG_STR(log,LOG4CPLUS_TEXT("Wait overlapped I/O finished."));*/
	delete []m_buffer.buf;
	LOG4CPLUS_DEBUG_STR(log,LOG4CPLUS_TEXT("Free buffer finished."));
	delete m_httpResponseHeader;
	LOG4CPLUS_DEBUG_STR(log,LOG4CPLUS_TEXT("Free http response header data finished."));
	FreeInsteadContext();
#if _DEBUG
	if(m_debugFileHandle!=NULL)
	{
		CloseHandle(m_debugFileHandle);
		LOG4CPLUS_DEBUG_STR(log,LOG4CPLUS_TEXT("Close debug file handle finished."));
	}
#endif
	LOG4CPLUS_DEBUG_STR(log,LOG4CPLUS_TEXT("End to dispose client."));
}

void ClientContext::InitializeInsteadContext()
{
	FreeInsteadContext();
	m_insContext=new InsTempContext();
}

void ClientContext::FreeInsteadContext()
{
	if(m_insContext!=NULL)
	{
		delete m_insContext;
		m_insContext=NULL;
		LOG4CPLUS_DEBUG_STR(log,LOG4CPLUS_TEXT("Free instead context finished."));
	}
}

void ClientContext::ReplaceDestinationWithInsteadContext()
{
	LOG4CPLUS_DEBUG_STR(log,LOG4CPLUS_TEXT("Start to replace destination."));
	if(m_destSock!=NULL)
	{
		shutdown(m_destSock,SD_BOTH);
		closesocket(m_destSock);
	}
	m_destSock=m_insContext->TempSock();
	m_insContext->SetTempSock(NULL);
	delete m_httpResponseHeader;
	m_httpResponseHeader=&(m_insContext->TempHttpResponseHeader());
	m_insContext->SetTempHttpResponseHeader(NULL);
	FreeInsteadContext();
	string message;
	message.append(m_httpRequest.FullRequestUrl());
	message.append("\r\nreplaced.");
	NotifyProc(NOTIFY_SOURCE_REPLACED,message.c_str());
	LOG4CPLUS_DEBUG_STR(log,LOG4CPLUS_TEXT("End to replace destination."));
}

void ClientContext::InitAsyncParam(OVERLAPPED *ovl,WSABUF *buffer)
{
	::ZeroMemory(ovl,sizeof(OVERLAPPED));
	buffer->buf=new char[CLIENTCONTEXT_BUFFER_SIZE];
	buffer->len=CLIENTCONTEXT_BUFFER_SIZE;
}